﻿namespace Liger.Web.UI
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Liger.Web.Common;
    using Liger.Web.Common.Extensions;
    using System.ComponentModel;
    using Liger.Web.Javascript;

    public class Grid : UIComponentBase
    { 
        public Grid()
            : this(new StringBuilder())
        {

        } 
        public Grid(StringBuilder writer)
            : base(writer)
        {
            Columns = new List<GridColumn>(); 
            BaseSettings = new GridBaseSettings();
            Checkbox = new GridCheckboxSettings();
            ColumnSettings = new GridColumnSettings();
            Editing = new GridEditingSettings();
            Grouping = new GridGroupingSettings();
            Paging = new GridPagingSettings();
            RowSettings = new GridRowSettings();
            Sorting = new GridSortingSettings();
            Total = new GridTotalSettings();
            Ajax = new GridAjaxSettings();
            Properties = new Dictionary<string, object>();
            ComponentName = "Grid";
            PluginName = "ligerGrid";
            DataAction = GridDataActionType.server;
            JSWriter.PropertyVariableCase = true;
            if(this.Manager.IsNullOrEmpty())
                this.Manager = ID;
        }
        /// <summary>
        /// 返回ligerGrid的Manager
        /// </summary>
        public string Manager
        {
            get;
            set;
        }

        /// <summary>
        /// 列
        /// </summary>
        public IList<GridColumn> Columns
        {
            get;
            set;
        }
        public IList<GridColumn> VisibleColumns
        {
            get
            {
                return Columns.Where(c => c.Visible.HasValue && c.Visible.Value).ToList();
            }
        }

        /// <summary>
        /// 明细支持
        /// </summary>
        public GridDetailParm Detail
        {
            get;
            set;
        }

        /// <summary>
        /// treeGrid模式
        /// </summary>
        public GridTreeParm Tree
        {
            get;
            set;
        }

        /// <summary>
        /// 提交数据的方式：本地(local)或(server),选择本地方式时将在客服端分页、排序
        /// </summary>
        public GridDataActionType DataAction
        {
            get;
            set;
        }

        /// <summary>
        /// 基础设置 的配置信息
        /// </summary>
        public GridBaseSettings BaseSettings
        {
            get;
            set;
        }
        /// <summary>
        /// 复选框模式 的配置信息
        /// </summary>
        public GridCheckboxSettings Checkbox
        {
            get;
            set;
        }
        /// <summary>
        /// 表格列 的配置信息
        /// </summary>
        public GridColumnSettings ColumnSettings
        {
            get;
            set;
        }
        /// <summary>
        /// 可编辑 的配置信息
        /// </summary>
        public GridEditingSettings Editing
        {
            get;
            set;
        }
        /// <summary>
        /// 可分组 的配置信息
        /// </summary>
        public GridGroupingSettings Grouping
        {
            get;
            set;
        }
        /// <summary>
        /// 服务器模式 的配置信息
        /// </summary>
        public GridAjaxSettings Ajax
        {
            get;
            set;
        }
        /// <summary>
        /// 可分页 的配置信息
        /// </summary>
        public GridPagingSettings Paging
        {
            get;
            set;
        }
        /// <summary>
        /// 表格行 的配置信息
        /// </summary>
        public GridRowSettings RowSettings
        {
            get;
            set;
        }
        /// <summary>
        /// 可排序 的配置信息
        /// </summary>
        public GridSortingSettings Sorting
        {
            get;
            set;
        }
        /// <summary>
        /// 可统计 的配置信息
        /// </summary>
        public GridTotalSettings Total
        {
            get;
            set;
        }

        public object Toolbar
        {
            get;
            set;
        }

        /// <summary>
        /// 其他可扩展的属性
        /// </summary>
        public Dictionary<string, object> Properties
        {
            get;
            set;
        }


        private string GetColumnsJSON(IList<GridColumn> columns)
        {
            //Write Columns JSON
            IJavascriptObjectWriter jswcolumns = new JavascriptObjectWriter();
            jswcolumns.PropertyVariableCase = JSWriter.PropertyVariableCase;
            jswcolumns.WriteArray();
            for (int i = 0; columns != null && i < columns.Count; i++)
            {
                GridColumn column = columns[i];
                jswcolumns.WriteOjbect()
                    .WriteProperty("Name", column.Name)
                    .WriteProperty("Display", string.IsNullOrEmpty(column.Display) ? column.Name : column.Display)
                    .WritePropertyObject("Type", column.Type)
                    .WritePropertyObject("Align", column.Align)
                    .WriteProperty("Format", column.Format)
                    .WriteProperty("Width",column.Width)
                    .WriteProperty("IsSort", column.IsSort)
                    .WriteProperty("MinWidth", column.MinWidth)
                    .WriteProperty("MaxWidth", column.MaxWidth)
                    .WriteProperty("Render", column.Render)
                    .WriteProperty("Editor", () =>
                    {
                        if (column.Editor == null || column.Editor.Type == null) return null;
                        IJavascriptObjectWriter jsweditor = new JavascriptObjectWriter();
                        jsweditor.PropertyVariableCase = JSWriter.PropertyVariableCase;
                        jsweditor.WriteOjbect();
                        jsweditor.WriteProperty("Type", column.Editor.Type)
                            .WriteProperty("MinValue", column.Editor.MinValue)
                            .WriteProperty("MaxValue", column.Editor.MaxValue)
                            .WriteProperty("ValueColumnName", column.Editor.ValueColumnName)
                            .WriteProperty("DisplayColumnName", column.Editor.DisplayColumnName)
                            .WritePropertyObject("Data", column.Editor.Data)
                            .WriteProperty("OnChange", column.Editor.OnChange)
                            .WriteProperty("OnChanged", column.Editor.OnChanged)
                            .WriteProperty("P", column.Editor.P);

                        if (column.Editor.Options.Keys.Count > 0)
                        {

                            jsweditor.WriteProperty("Options", () =>
                                {
                                    IJavascriptObjectWriter jsweditorOptions = new JavascriptObjectWriter();
                                    jsweditorOptions.PropertyVariableCase = JSWriter.PropertyVariableCase;
                                    jsweditorOptions.WriteOjbect();
                                    foreach (var key in column.Editor.Options.Keys)
                                    {
                                        var value = column.Editor.Options[key];
                                        jsweditorOptions.WritePropertyObject(key, value);
                                    }
                                    jsweditorOptions.WriteEndOjbect();
                                    return jsweditorOptions.Output();
                                }
                            );

                        } 
                        foreach (var prop in column.Properties)
                        {
                            jsweditor.WritePropertyObject(prop.Key, prop.Value);
                        }
                        jsweditor.WriteEndOjbect();
                        return jsweditor.Output();
                    });
                if (column.VisibleColumns != null)
                    jswcolumns.WriteProperty("Columns", () => GetColumnsJSON(column.VisibleColumns));
                jswcolumns.WriteEndOjbect();
            }
            jswcolumns.WriteEndArray();
            return jswcolumns.Output();
        }
        private void disableSort(IList<GridColumn> columns)
        {
            if (columns == null || columns.Count == 0) return;
            foreach (var column in columns)
            {
                column.IsSort = false;
                disableSort(column.Columns);
            }
        }

        /// <summary>
        /// 获取Grid参数的JSON
        /// </summary>
        /// <returns></returns>
        public string GetGridParmJSON()
        {
            IJavascriptObjectWriter JSWriter = new JavascriptObjectWriter();
            JSWriter.PropertyVariableCase = this.JSWriter.PropertyVariableCase;
            JSWriter.WriteOjbect();
             
            //Checkbox
            if (Checkbox.Enabled)
            {
                JSWriter.WriteProperty("Checkbox", true)
                    .WriteProperty("IsChecked", Checkbox.IsChecked)
                    .WriteProperty("SelectRowButtonOnly", Checkbox.SelectRowButtonOnly);
            }
            else
            {
                JSWriter.WriteProperty("Checkbox", false);
            }
            //Column Setting
            JSWriter.WriteProperty("ColumnWidth", ColumnSettings.ColumnWidth)
                .WriteProperty("MinColToggle", ColumnSettings.MinColToggle)
                .WriteProperty("AllowAdjustColWidth", ColumnSettings.AllowAdjustColWidth)
                .WriteProperty("AllowHideColumn", ColumnSettings.AllowHideColumn);

            //Editing 
            if (Editing.Enabled)
            {
                JSWriter.WriteProperty("EnabledEdit", true)
                    .WriteProperty("DblClickToEdit", Editing.DblClickToEdit);
            }
            //Grouping
            if (Grouping.Enabled)
            {
                JSWriter.WriteProperty("GroupColumnName", Grouping.GroupColumnName)
                    .WriteProperty("GroupColumnDisplay", Grouping.GroupColumnDisplay);
            }
            //Ajax 
            if (Ajax.Enabled)
            {
                JSWriter.WriteProperty("DataType", GridDataType.server.ToString())
                    .WriteProperty("Url", Ajax.URL)
                    .WriteProperty("Method", Ajax.Method)
                    .WriteProperty("PageParmName", Ajax.PageParmName)
                    .WriteProperty("PagesizeParmName", Ajax.PagesizeParmName)
                    .WriteProperty("SortnameParmName", Ajax.SortnameParmName)
                    .WriteProperty("SortorderParmName", Ajax.SortorderParmName);

                if (Ajax.SortName.HasValue())
                {
                    JSWriter.WriteProperty("SortName", Ajax.SortName)
                        .WriteProperty("SortOrder", Ajax.SortOrder != null && Ajax.SortOrder.ToLower() == "asc" ? "asc" : "desc");
                }

                if (Ajax.Parms != null && Ajax.Parms.Keys.Count > 0 
                    ||
                    Ajax.AjaxParms != null && Ajax.AjaxParms.Keys.Count > 0
                    
                    )
                {
                    IJavascriptObjectWriter ajaxParmWriter = new JavascriptObjectWriter();
                    ajaxParmWriter.WriteArray();
                    if (Ajax.Parms != null && Ajax.Parms.Keys.Count > 0)
                    {
                        foreach (var key in Ajax.Parms.Keys)
                        {
                            ajaxParmWriter.WriteOjbect();
                            ajaxParmWriter.WriteProperty("name", key);
                            ajaxParmWriter.WriteProperty("value", Ajax.Parms[key]);
                            ajaxParmWriter.WriteEndOjbect();
                        }
                    }
                    else if (Ajax.AjaxParms != null && Ajax.AjaxParms.Keys.Count > 0)
                    {
                        foreach (var key in Ajax.AjaxParms.Keys)
                        {
                            ajaxParmWriter.WriteOjbect();
                            ajaxParmWriter.WriteProperty("name", key);
                            ajaxParmWriter.WritePropertyObject("value", Ajax.AjaxParms[key]);
                            ajaxParmWriter.WriteEndOjbect();
                        }
                    }
                    ajaxParmWriter.WriteEndArray();

                    JSWriter.WriteProperty("Parms", () => ajaxParmWriter.Output());
                }
                
            }
            else
            {
                JSWriter.WriteProperty("DataType", GridDataType.local.ToString())
                    .WritePropertyNullableString("url", "");

            }
            JSWriter.WriteProperty("StatusName", Ajax.StatusName)
                .WriteProperty("Root", Ajax.Root)
                .WriteProperty("Record", Ajax.Record);

            //toolbar
            JSWriter.WritePropertyObject("Toolbar", this.Toolbar);

            //Paging 
            JSWriter.WriteProperty("UsePager", Paging.UsePager);

            if(Paging.UsePager)
            {
                JSWriter.WriteProperty("Page", Paging.Page)
                   .WriteProperty("PageSize", Paging.PageSize)
                   .WriteProperty("PageSizeOptions", Paging.PageSizeOptions);
            }
                   
            //Sorting
            if (Sorting.Enabled)
            {
                JSWriter.WriteProperty("EnabledSort", true); 
            }
            else
            {
                JSWriter.WriteProperty("EnabledSort", false);
                disableSort(this.Columns);
            }

            JSWriter.WriteProperty("DataAction", this.DataAction.ToString());

            //Total
            JSWriter.WriteProperty("TotalRender", Total.TotalRender);

            //Columns
            JSWriter.WriteProperty("Columns", () => GetColumnsJSON(this.VisibleColumns));


            //Detail
            if (this.Detail != null && this.Detail.DetailGrid != null)
            {   
                string detailGridParmJSON = this.Detail.DetailGrid.GetGridParmJSON();
                 
                JSWriter.WriteProperty("Detail", () => @"{onShowDetail:function(rowdata,detailPanel){
                    var detailGrid = document.createElement('div'); 
                    jQuery(detailPanel).append(detailGrid);
                    jQuery(detailGrid).css('margin',9).ligerGrid(" + detailGridParmJSON + @");
                }}");
            }

            //Base Setting
            JSWriter.WritePropertyObject("Data", BaseSettings.Data)
                .WriteProperty("Title", BaseSettings.Title)
                .WriteProperty("Width", BaseSettings.Width)
                .WriteProperty("Height", BaseSettings.Height)
                .WriteProperty("Resizable", BaseSettings.Resizable)
                .WriteProperty("ShowTableToggleBtn", BaseSettings.ShowTableToggleBtn)
                .WriteProperty("SwitchPageSizeApplyComboBox", BaseSettings.SwitchPageSizeApplyComboBox)
                .WriteProperty("IsScroll", BaseSettings.IsScroll)
                .WriteProperty("InWindow", BaseSettings.InWindow)
                .WriteProperty("DateFormat", BaseSettings.DateFormat)
                .WriteProperty("HeightDiff", BaseSettings.HeightDiff)
                .WriteProperty("CssClass", BaseSettings.CssClass)
                .WriteProperty("DelayLoad", BaseSettings.DelayLoad)
                .WriteProperty("Where", BaseSettings.Where)
                .WriteProperty("RenderDate", BaseSettings.RenderDate);

            if (this.Properties != null)
            {
                foreach (var prop in this.Properties.Keys)
                {
                    var value = this.Properties[prop];
                    JSWriter.WritePropertyObject(prop, value);
                }
            }

            //Client Events
            if(this.Events != null){
            foreach (var even in this.Events)
            {
                JSWriter.WriteProperty(even.Key, even.Value);
            }
                }

            JSWriter.WriteEndOjbect();

            return JSWriter.Output();
        }


        public override void WriteHTML()
        {
            if (!ID.HasValue())
                ID = "grid" + System.Guid.NewGuid().ToString();

            Writer.Append("<div id='{0}'></div>".FormatWith(ID)); 
        }
        public override void WriteScript()
        {
            if (base.LoadInDocumentReady)
            {
                JSWriter.WriteJQueryOnLoad();
            }
            if (this.Manager.HasValue())
            {
                JSWriter.Append("window.{0} = ".FormatWith(this.Manager));
            }
            JSWriter.WriteJQueryPlugin(ID, "ligerGrid");
            JSWriter.Append(GetGridParmJSON());
            JSWriter.WriteEndJQueryPlugin();
            if (base.LoadInDocumentReady)
            {
                JSWriter.WriteEndJQueryOnLoad();
            } 
        }
    }
}
